home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
...taking it to the Macs!
/
...taking it to the Macs!.iso
/
Extras
/
ActiveX Mac SDK
/
ActiveX SDK
/
Container Common
/
cpropbag.cpp
< prev
next >
Wrap
Text File
|
1997-01-03
|
18KB
|
663 lines
//
// CPropBag.CPP
//
// Copyright (C) Microsoft Corporation, 1996
//
#include "headers.h"
#define PBCONTENTS "%%pbcontents%%"
//======================================================================
//
CPropertyBag::CPropertyBag()
: m_cRef(1), m_pPropertiesTail(NULL),
m_pPropertiesHead(NULL), m_cProperties(0), m_pbContents(0)
{
// This is a standalone COM object...
// increase the ref count on the DLL so the DLL knows not to unload
// until the last object has been destroyed
DLLAddRef();
}
//======================================================================
//
CPropertyBag::~CPropertyBag()
{
DLLRelease();
deletePropertyList();
//
// BUGBUG: davidna 5/7/96: Beta1 Hack.
//
// m_pbContents exists only if the OC knows of the %%PBCONTENTS%% name
// and reads it.
// Hopefully this just means the JavaOC
//
if(m_pbContents)
{
ULONG x =0, y = 2 * m_cProperties;
char far * *pContents = (char **) ((ULONG)m_pbContents + sizeof(ULONG));
// The storage for m_pbContents goes like this:
// We have pointers to the name/value pairs following the
// the count (ULONG) of items (or pairs)
// we allocated storage for all the values so we must now set them free
// pContents[0] is the first item name and
// pContents[1] is the first item value
// so bump past the name
pContents++;
for(x = 0; x < y; x+=2)
{
if(pContents[x])
GTR_FREE(pContents[x]); // free the allocation for the value
}
GTR_FREE(m_pbContents);
}
}
/*******************************************************************
NAME: CPropertyBag::AddRef
SYNOPSIS: Standard implementation of IUnknown::AddRef.
********************************************************************/
STDMETHODIMP_(ULONG) CPropertyBag::AddRef(void)
{
return ++m_cRef;
}
/*******************************************************************
NAME: CPropertyBag::Release
SYNOPSIS: Standard implementation of IUnknown::Release
********************************************************************/
STDMETHODIMP_(ULONG) CPropertyBag::Release(void)
{
if (--m_cRef == 0)
{
delete this;
return 0;
}
return m_cRef;
}
/*******************************************************************
NAME: CPropertyBag::QueryInterface
SYNOPSIS: Standard implementation of IUnknown::QueryInterface.
NOTES:
********************************************************************/
STDMETHODIMP CPropertyBag::QueryInterface(REFIID riid, LPVOID *ppvObj)
{
// ppvObj must not be NULL
ASSERT(ppvObj != NULL);
if (ppvObj == NULL)
return E_INVALIDARG;
*ppvObj = NULL;
if (riid == IID_IUnknown)
*ppvObj = this;
else
if (riid == IID_IPropertyBag)
*ppvObj = this;
else
return E_NOINTERFACE; // Otherwise, don't delegate to HTMLObj!!
if (*ppvObj != NULL) // Should always be non-NULL at this point, but just to be safe...
((LPUNKNOWN)*ppvObj)->AddRef();
return S_OK;
}
//======================================================================
//
// Asks the property bag to read the property named with pwcPropName
// into the caller-initialized VARIANT in pVar.
//
//
STDMETHODIMP_(HRESULT) CPropertyBag::Read
(
LPCOLESTR pszPropName,
VARIANT *pVar,
IErrorLog *pErrorLog
)
{
#pragma unused (pErrorLog)
if(NULL == m_pPropertiesHead)
return E_INVALIDARG;
ASSERT(NULL != pszPropName);
if(NULL == pszPropName)
return E_POINTER;
ASSERT(NULL != pVar);
if(NULL == pVar)
return E_POINTER;
HRESULT hr;
PROPERTYLIST *pCurProp = m_pPropertiesHead;
#if 0
if(0 == strcmp(pszPropName, PBCONTENTS))
{
hr = GetPropertyBagContents(pVar,pErrorLog);
return hr;
}
#endif
while(pCurProp != NULL)
{
// Paranoia
ASSERT((NULL != pCurProp->pProperty) && (NULL != pCurProp->pProperty->pszName));
if(((NULL != pCurProp->pProperty) && (NULL != pCurProp->pProperty->pszName)))
{
if(0 == strcmp(pszPropName, pCurProp->pProperty->pszName) )
{
// Caller didn't specify
if(pVar->vt == VT_EMPTY)
pVar->vt = VT_I4; // assume long?
hr = VariantChangeType(pVar, pCurProp->pProperty->pvarValue, 0, pVar->vt);
break;
}
}
pCurProp = (PROPERTYLIST *)pCurProp->pNext;
}
// at the end of the list?
if(NULL == pCurProp)
return E_INVALIDARG;
if(SUCCEEDED(hr))
return S_OK;
else
return E_FAIL; // didn't find it
}
//======================================================================
//
// Asks the property bag to read the property named with pszPropName
// into the caller-initialized VARIANT in pVar.
//
//
BOOL CPropertyBag::find
(
const char *pszPropName,
PROPERTY * *ppProp
)
{
if(NULL == m_pPropertiesHead)
return FALSE;
ASSERT(NULL != pszPropName);
if(NULL == pszPropName)
return FALSE;
PROPERTYLIST *pCurProp = m_pPropertiesHead;
while(pCurProp != NULL)
{
// Paranoia
ASSERT((NULL != pCurProp->pProperty) && (NULL != pCurProp->pProperty->pszName));
if(((NULL != pCurProp->pProperty) && (NULL != pCurProp->pProperty->pszName)))
{
if(0 == strcmp(pszPropName, pCurProp->pProperty->pszName) )
{
*ppProp = pCurProp->pProperty;
return TRUE;
}
}
pCurProp = (PROPERTYLIST *)pCurProp->pNext;
}
return FALSE; // didn't find it
}
//======================================================================
//
// Asks the property bag to save the property named with
// pszPropName using the type and value in the
// caller-initialized VARIANT in pVar.
//
STDMETHODIMP_(HRESULT) CPropertyBag::Write
(
LPCOLESTR pwcPropName,
VARIANT *pVar
)
{
PROPERTY *pProperty = new(PROPERTY);
pProperty->pvarValue = new(VARIANT);
VariantInit(pProperty->pvarValue);
// make a copy
VariantCopy(pProperty->pvarValue, pVar);
pProperty->pszName = (char*)GTR_MALLOC((strlen(pwcPropName) + 1)*sizeof(char));
strcpy(pProperty->pszName, pwcPropName);
addToPropertyList(pProperty);
return S_OK;
}
//======================================================================
//
BOOL CPropertyBag::addToPropertyList(PROPERTY *pProperty)
{
PROPERTYLIST * pNewProp = new(PROPERTYLIST);
if(NULL == m_pPropertiesHead)
{
m_pPropertiesHead = pNewProp;
m_pPropertiesHead->pPrev = NULL;
m_pPropertiesHead->pNext = NULL;
m_pPropertiesTail = m_pPropertiesHead;
}
else
m_pPropertiesTail->pNext = pNewProp;
// add it to the list
pNewProp->pProperty = pProperty;
pNewProp->pPrev = m_pPropertiesTail;
pNewProp->pNext = NULL;
m_pPropertiesTail = pNewProp;
m_cProperties++;
return TRUE;
}
//======================================================================
//
BOOL CPropertyBag::deletePropertyList()
{
if(NULL == m_pPropertiesHead)
return TRUE;
PROPERTYLIST *pCurProp = m_pPropertiesHead;
while(pCurProp->pNext != NULL)
{
if(pCurProp->pProperty->pvarValue->vt == VT_BSTR &&
pCurProp->pProperty->pvarValue->bstrVal)
CoTaskMemFree(pCurProp->pProperty->pvarValue->bstrVal);
SAFEDELETE( pCurProp->pProperty->pvarValue );
if(pCurProp->pProperty->pszName)
CoTaskMemFree( pCurProp->pProperty->pszName );
SAFEDELETE( pCurProp->pProperty );
pCurProp = (PROPERTYLIST *)pCurProp->pNext;
SAFEDELETE( pCurProp->pPrev );
}
// remove the last one
if(pCurProp->pProperty->pvarValue->vt == VT_BSTR &&
pCurProp->pProperty->pvarValue->bstrVal)
CoTaskMemFree(pCurProp->pProperty->pvarValue->bstrVal);
SAFEDELETE( pCurProp->pProperty->pvarValue );
if(pCurProp->pProperty->pszName)
CoTaskMemFree( pCurProp->pProperty->pszName );
SAFEDELETE( pCurProp->pProperty );
SAFEDELETE( pCurProp );
m_pPropertiesHead = NULL;
m_pPropertiesTail = NULL;
return TRUE;
}
void CPropertyBag::AddParam(const char *name, const char *value )
{
int length;
// Add the param to the property bag
VARIANT *pVar = new(VARIANT);
// Fill in the VARIANT structure
//
VariantInit(pVar);
length = strlen((char *) value);
// VARIANT:BSTR's must be allocated with SysAllocString
// (Copy 2)
pVar->vt = VT_BSTR;
// A BSTR is a VB counted string where the first DWORD is the
// length of the string, not including the null terminator,
// followed by a null-terminated string.
pVar->bstrVal = (char*) CoTaskMemAlloc(sizeof(DWORD) + length + 1);
*((LPDWORD) pVar->bstrVal) = (DWORD) length;
memcpy(pVar->bstrVal + sizeof(DWORD), value, length + 1);
ASSERT(NULL != pVar->bstrVal);
if(NULL == pVar->bstrVal)
return;
// This is a wrapper that handles the CString
// to OLE string conversion
this->Write(name, pVar);
CoTaskMemFree(pVar->bstrVal);
// pPropertyBag->Write() made a copy (3 copies all told, a bit excessive I think, necessary?)
// so SAFEDELETE() this now
SAFEDELETE( pVar );
return;
}
#if 0
//======================================================================
//
// set the ExtentX & ExtentY values for the property bag
// ulWidth & ulHeight are given in pixels.
//
void CPropertyBag::setExtents(ULONG ulWidth, ULONG ulHeight)
{
ASSERT(pSite != NULL);
if(NULL == pSite)
return;
PROPERTY * pProp;
BSTR pBstr[2] = {NULL,NULL};
char szVal[20];
CPropertyBag *pPropertyBag = NULL;
// See if this CSite already has a Property Bag
pPropertyBag = pSite->GetPropertyBag();
// If not create a new one and set it to the CSite
// The CSite method will addRef it in either case
//
if (NULL == pPropertyBag)
{
// Create a brand new property bag
pPropertyBag = new( CPropertyBag());
ASSERT(NULL != pPropertyBag);
if(NULL == pPropertyBag)
return;
pSite->SetPropertyBag(pPropertyBag);
}
else
{
// Do these exist already?
if(pPropertyBag->find("_extentX", &pProp)
&& pPropertyBag->find("_extentY", &pProp))
return;
}
VARIANT *pVar[] = {new(VARIANT), new(VARIANT) };
ASSERT((NULL != pVar[0]) && (NULL != pVar[1]));
if ((NULL == pVar[0]) || (NULL == pVar[1]))
{
if(pVar[0])
SAFEDELETE(pVar[0]);
if(pVar[1])
SAFEDELETE(pVar[1]);
return;
}
VariantInit(pVar[0]);
VariantInit(pVar[1]);
pVar[0]->vt = VT_BSTR;
pVar[1]->vt = VT_BSTR;
SIZEL szPix={ulWidth,ulHeight}, szHim={0,0};
XformSizeInPixelsToHimetric(NULL, &szPix, &szHim);
// allocates pBstr
Ansi2Unicode(_ultoa( szHim.cx, szVal, 10 ), &pBstr[0]);
Ansi2Unicode(_ultoa( szHim.cy, szVal, 10 ), &pBstr[1]);
ASSERT((NULL != pBstr[0]) && (NULL != pBstr[1]));
if ((NULL == pBstr[0]) || (NULL == pBstr[1]))
return;
// VARIANT:BSTR's must be allocated with SysAllocString
pVar[0]->bstrVal = SysAllocString(pBstr[0]);
pVar[1]->bstrVal = SysAllocString(pBstr[1]);
ASSERT((NULL != pVar[0]->bstrVal) && (NULL != pVar[1]->bstrVal));
if ((NULL == pVar[0]->bstrVal) || (NULL == pVar[1]->bstrVal))
{
if(pVar[0]->bstrVal)
SAFEDELETE(pVar[0]->bstrVal);
if(pVar[1])
SAFEDELETE(pVar[1]->bstrVal);
if(pVar[0])
SAFEDELETE(pVar[0]);
if(pVar[1])
SAFEDELETE(pVar[1]);
return;
}
// This is a wrapper that handles the CString
// to OLE string conversion
pPropertyBag->lpstrWrite("_extentX", pVar[0]);
pPropertyBag->lpstrWrite("_extentY", pVar[1]);
// SAFEDELETE() these now
SAFEDELETE( pVar[0]);
SAFEDELETE( pVar[1]);
// Don't need these any longer
if(pBstr[0])
GTR_FREE(pBstr[0]);
if(pBstr[1])
GTR_FREE(pBstr[1]);
}
//======================================================================
//
// Note: BUGBUG only name & value are used in this interim implementation
//
//
//
void HText_addParamToPropertyBag(HText *text, const char *name, const char *type,
const char *value,const char *valueRef,
const char *attr, const int iInsertTagElement )
{
if(NULL == name)
return;
if(NULL == value)
return;
// Find the object we're associated with, using iInsertTagElement
if (iInsertTagElement <= -1) // we don't have an association
return; // </INSERT> with no <INSERT>
// Get a pointer to the Objects Element
ELEMENT *pElement = &(text->w3doc->aElements[iInsertTagElement]);
ASSERT(pElement != NULL);
if(NULL == pElement)
return;
// Get the Object
CInsertableObject *pObj = (CInsertableObject *)pElement->pInsert;
if ( NULL == pObj)
return;
// Get the objects CSite
CSite *pSite = NULL;
CPropertyBag *pPropertyBag = NULL;
HRESULT hr = pObj->GetSite(&pSite);
ASSERT(SUCCEEDED(hr) && pSite != NULL);
if (!SUCCEEDED(hr) || NULL == pSite)
return;
// See if this CSite already has a Property Bag
pPropertyBag = pSite->GetPropertyBag();
// If not create a new one and set it to the CSite
// The CSite method will addRef it in either case
//
if (NULL == pPropertyBag)
{
// Create a brand new property bag
pPropertyBag = new (CPropertyBag());
hr = pSite->SetPropertyBag(pPropertyBag);
}
// Add the param to the property bag
VARIANT *pVar = new(VARIANT);
BSTR pBstr = NULL;
// Fill in the VARIANT structure
//
VariantInit(pVar);
// Convert ANSI to Unicode (copy 1)
hr = Ansi2Unicode(value, &pBstr);
ASSERT(NULL != pBstr);
if(NULL == pBstr)
return;
// VARIANT:BSTR's must be allocated with SysAllocString
// (Copy 2)
pVar->vt = VT_BSTR;
pVar->bstrVal = SysAllocString(pBstr);
// Don't need this copy any longer
GTR_FREE(pBstr);
ASSERT(NULL != pVar->bstrVal);
if(NULL == pVar->bstrVal)
return;
// This is a wrapper that handles the CString
// to OLE string conversion
pPropertyBag->lpstrWrite(name, pVar);
// pPropertyBag->Write() made a copy (3 copies all told, a bit excessive I think, necessary?)
// so SAFEDELETE() this now
SAFEDELETE( pVar );
return;
}
//======================================================================
//
// BUGBUG:HACKHACK davidna 5/7/96 Beta1 Hack
//
// Called when PropertyBag::read() is called with the Property name set
// to "%%pbcontents%%"
//
// Put the contents in a block of memory as name & value pairs.
// Stored as char FAR * 's
// Return this in the callers Variant
//
// The storage goes like this:
// We have pointers to the name/value pairs following the
// the count (ULONG) of items (or pairs) in m_pbContents
//
// we allocate storage for all the values so we must them free later
//
//
HRESULT CPropertyBag::GetPropertyBagContents
(
VARIANT *pVar,
IErrorLog *pErrorLog
)
{
PROPERTYLIST *pCurProp = m_pPropertiesHead;
char far * *pContents;
ASSERT(NULL != pVar);
if(NULL == pVar)
return E_POINTER;
// Must be this type for this HACK!
if(pVar->vt != (VT_BYREF|VT_UI1) )
return E_INVALIDARG;
if(NULL == m_pPropertiesHead)
return E_FAIL;
// only allowed to do this once
//
ASSERT(NULL == m_pbContents);
if(NULL != m_pbContents)
return E_FAIL;
// allocate storage for the count (ULONG/number of items)
// plus each of the items or name/value pairs
//
m_pbContents = (LPSTR *) GTR_MALLOC(sizeof(ULONG) + (sizeof(char far *) * m_cProperties)*2);
ULONG *pcItems = (ULONG *)m_pbContents;
*(ULONG *)m_pbContents = m_cProperties; // first ULONG is count of items
// Bump the pointer past the length
pContents = (char * *) ((ULONG)m_pbContents + sizeof(ULONG));
// Fill in the blanks
while(pCurProp != NULL)
{
ASSERT((NULL != pCurProp->pProperty) && (NULL != pCurProp->pProperty->pszName));
if(((NULL != pCurProp->pProperty) && (NULL != pCurProp->pProperty->pszName)))
{
// store a pointer to the name
//
*pContents = pCurProp->pProperty->pszName;
pContents++;
// Now store a pointer to the value
// Convert to ansi 'cause Java Applets probably won't like BSTR's
// and they're our only users of this
//
// Ansi2Unicode allocates the memory so we need to remember
// to deallocate this later
//
if(FAILED(Unicode2Ansi((pCurProp->pProperty->pvarValue->bstrVal), pContents)) )
{
GTR_FREE(*pContents);
GTR_FREE(m_pbContents);
m_pbContents = NULL;
return E_FAIL;
}
else
pContents++;
}
pCurProp = (PROPERTYLIST *)pCurProp->pNext;
}
// put in variant
pVar->pbVal = (unsigned char *)m_pbContents;
return S_OK;
}
#endif